package com.mock.water.modules.system.user.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mock.water.config.shiro.JwtToken;
import com.mock.water.core.utils.AjaxResult;
import com.mock.water.core.utils.ConvertUtil;
import com.mock.water.core.utils.JwtUtils;
import com.mock.water.modules.system.role.service.RoleService;
import com.mock.water.modules.system.user.entity.UserEntity;
import com.mock.water.modules.system.user.model.UserDto;
import com.mock.water.modules.system.user.model.UserVo;
import com.mock.water.modules.system.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.*;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author ifredomvip@gmail.com
 * @version 1.0.0
 * @date 2022/10/13 16:46
 **/

@RestController
@RequestMapping("")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @GetMapping("/{url}")
    public String redirect(@PathVariable("url") String url) {
        return url;
    }

    @GetMapping("/unauth")
    @ResponseBody
    public String unauth() {
        return "未授权没有访问权限";
    }

    /**
     * 注册新用户
     *
     * @param userVo 新用户信息
     */

    @PostMapping("/register")
    public AjaxResult registerUser(@Validated @RequestBody UserVo userVo, BindingResult bindingResult, @ModelAttribute("author") String author) {
        UserEntity user = new UserEntity();

        String salt = RandomStringUtils.randomAlphanumeric(20);

        //加密
        SimpleHash simpleHash = new SimpleHash("md5", userVo.getPassword(), salt, 3);
        String hashPassword = simpleHash.toString();

        user.setUsername(userVo.getUsername());
        user.setPassword(hashPassword);
        user.setSalt(salt);
        user.setStatus(0);
        user.setCreateTime(new Date());

        //如果有错误提示信息
        if (bindingResult.hasErrors()) {
            System.out.println("有错误");
            Map<String, String> map = new HashMap<>(16);
            bindingResult.getFieldErrors().forEach((item) -> {
                String message = item.getDefaultMessage();
                String field = item.getField();
                map.put(field, message);
            });
            //返回提示信息
            return AjaxResult.error(map.toString());
        }

        userService.save(user);
        return AjaxResult.success();
    }


    @PostMapping("/login")
    public AjaxResult loginUser(@Validated @RequestBody UserVo userVo, BindingResult bindingResult) {


        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userVo.getUsername(),userVo.getPassword());
//        token.setRememberMe(false);

        try {
            subject.login(token);
            log.info("登录成功");
        } catch (AuthenticationException ae) {
            return AjaxResult.error("账号或密码不正确2");
        }

        UserEntity userEntity = (UserEntity) subject.getPrincipal();
        UserDto blogDto = ConvertUtil.entityToVo(userEntity, UserDto.class);
        String generateToken = JwtUtils.generateToken(userEntity.getUsername(), JwtUtils.secret);
        blogDto.setToken(generateToken);

        return AjaxResult.success(blogDto);
    }


    @GetMapping("/token/{token}")
    public AjaxResult testWithToken(@PathVariable("token") String token) {
        log.info("findById请求时间：{}", LocalDateTime.now());

        Subject currentUser = SecurityUtils.getSubject();

        log.info("User [" + currentUser + "] logged in successfully.");

        System.out.println(currentUser.isAuthenticated());

        return AjaxResult.success("token： ");
    }

    @PostMapping("/logout")
    public AjaxResult logout() {
        Subject currentUser = SecurityUtils.getSubject();

        currentUser.logout();
        System.out.println("logout");
        return AjaxResult.success();
    }

    /**
     * 表示subject需要admin角色
     */
    @GetMapping("/a1")
    @RequiresRoles(value = {"admin"}, logical = Logical.AND)
    public AjaxResult testRequiresRoles() {

        List<UserEntity> user = userService.findAllCache("admin");

        System.out.println("testRequiresRoles");
        return AjaxResult.success(user);
    }

    /**
     * 表示subject需要权限user:create
     */
    @GetMapping("/a2")
    @RequiresPermissions(value = {"user:create"}, logical = Logical.AND)
    public void testRequiresPermissions() {
        System.out.println("testRequiresPermissions");
    }

    /**
     * 表示subject已经通过登录验证
     */
    @GetMapping("/a3")
    @RequiresAuthentication
    public void testRequiresAuthentication() {
        System.out.println("testRequiresAuthentication");
    }

    /**
     * 表示subject已经身份验证或者通过记住我登录
     */
    @GetMapping("/a4")
    @RequiresUser
    public void testRequiresUser() {
        System.out.println("testRequiresUser");
    }

    /**
     * 表示subject没有身份验证或通过记住我登录过，即是游客身份.
     */
    @GetMapping("/a5")
    @RequiresGuest
    public void testRequiresGuest() {
        System.out.println("testRequiresGuest");
    }

    @GetMapping("/dog")
    public String dog() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.hasRole("dog")) {
            return "dog√";
        } else {
            return "dog×";
        }
    }

}
